package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author huanghui
 * @since 2023-07-25
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;
    private final CourseClient courseClient;
    private final SearchClient searchClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;


    @Override
    public void saveQuestion(QuestionFormDTO questionDTO) {
        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.属性拷贝
        InteractionQuestion question = BeanUtils.copyBean(questionDTO, InteractionQuestion.class);
        //3.基础属性赋值
        question.setUserId(userId);
        save(question);


    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.查询当前问题
        InteractionQuestion question = getById(id);
        if (question == null) {
            return;
        }
        //3.判断是否是当前用户的问题
        if (!question.getUserId().equals(userId)){
            throw new BadRequestException("没有权限删除他人的问题");
        }
        //4.删除问题
        removeById(id);
        //问题删了，回答也得删除掉
        //5.删除回答
        replyMapper.deleteById(id);

    }

    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionDTO) {
        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.查询当前问题
        InteractionQuestion question = getById(id);
        if (question == null) {
            throw new BadRequestException("问题不存在");
        }

        //3.判断是否是当前用户的问题
        if (!question.getUserId().equals(userId)){
            throw new BadRequestException("没有权限修改他人的问题");
        }
        //4.开始修改问题
        InteractionQuestion q = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
        q.setId(id);
        q.setUserId(userId);
        updateById(q);
    }

    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery query) {
        //1.参数校验，课程id和小节id不能都为空
        Long courseId = query.getCourseId();
        Long sectionId = query.getSectionId();
        if (courseId == null && sectionId==null) {
            throw new BadRequestException("课程id和小节id不能为空");
        }
        //2.开启分页查询
        Page<InteractionQuestion> page = lambdaQuery()
                .select(InteractionQuestion.class, info -> !info.getProperty().equals("description"))
                .eq(query.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(courseId != null, InteractionQuestion::getCourseId, courseId)
                .eq(sectionId != null, InteractionQuestion::getSectionId, sectionId)
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        //3.查询提问者id和回答id
        //3.1查询提问者id
        Set<Long> userIds = records.stream().filter(
                record -> !record.getAnonymity() && !Objects.isNull(record.getUserId())
        ).map(InteractionQuestion::getUserId).collect(Collectors.toSet());

        //3.2查询回答id
        Set<Long> answerIds = records.stream()
                .map(InteractionQuestion::getLatestAnswerId)
                .filter(answerId -> !Objects.isNull(answerId))
                .collect(Collectors.toSet());

       //3.3 根据 回答者id  组装键值对(提问者id,回答者id)Map形式
        answerIds.remove(null);
        Map<Long, InteractionReply> replyMap = new HashMap<>(answerIds.size());
        if (ObjectUtils.isNotEmpty(answerIds)) {
            List<InteractionReply> replies = replyMapper.selectBatchIds(answerIds);
            replyMap =  replies.stream().collect(Collectors.toMap(InteractionReply::getId, Function.identity()));
            userIds.addAll(replies.stream().filter(r -> !r.getAnonymity()).map(r->r.getUserId()).collect(Collectors.toSet()));

        }
        // 3.4.根据id查询用户信息（提问者）
        userIds.remove(null);
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if(CollUtils.isNotEmpty(userIds)){
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }

        //4.封装vo
        List<QuestionVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            // 4.1.将PO转为VO
            QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);
            voList.add(vo);
            // 4.2.封装提问者信息
            if (!record.getAnonymity()) {
                UserDTO userDTO = userMap.get(record.getUserId());
                if (userDTO != null) {
                    vo.setUserName(userDTO.getName());
                    vo.setUserIcon(userDTO.getIcon());
                }
            }
            //4.3封装最近一次的回答的信息
            InteractionReply reply = replyMap.get(record.getLatestAnswerId());
            if (reply != null) {
                vo.setLatestReplyContent(reply.getContent());
                if (!reply.getAnonymity()) {
                    UserDTO user = userMap.get(reply.getUserId());
                    vo.setLatestReplyUser(user.getName());
                }
            }
        }
        return PageDTO.of(page,voList);

    }

    @Override
    public QuestionVO queryQuestionById(Long id) {
        //1.根据id查询数据
        InteractionQuestion question = getById(id);
        //2.数据校验
        if (question == null || question.getHidden()) {
            //没有数据或者被隐藏了
            return  null;
        }
        //3.查询提问者数据
        UserDTO user = null;
        if (!question.getAnonymity()) {
            user = userClient.queryUserById(question.getUserId());
        }
        //4.封装VO，数据拷贝
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        if (user != null) {
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        return vo;
    }


    @Override
    public PageDTO<QuestionAdminVO> queryAdminQuestionPage(QuestionAdminPageQuery query) {
        // 1.处理课程名称，得到课程id
        List<Long> courseIds = null;
        if (StringUtils.isNotBlank(query.getCourseName())){
            courseIds=searchClient.queryCoursesIdByName(query.getCourseName());
            if (CollUtils.isEmpty(courseIds)){
                return PageDTO.empty(0L,0L);
            }
        }
        // 2.分页查询
        Integer status = query.getStatus();
        LocalDateTime beginTime = query.getBeginTime();
        LocalDateTime endTime = query.getEndTime();
        Page<InteractionQuestion> page = lambdaQuery()
                .in(courseIds != null, InteractionQuestion::getCourseId, courseIds)
                .eq(status != null, InteractionQuestion::getStatus, status)
                .gt(beginTime != null, InteractionQuestion::getCreateTime, beginTime)
                .lt(endTime != null, InteractionQuestion::getCreateTime, endTime)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        // 3.准备VO需要的数据：用户数据、课程数据、章节数据
        Set<Long> userIds = new HashSet<>();
        Set<Long> cIds = new HashSet<>();
        Set<Long> cataIds = new HashSet<>();
        // 3.1.获取各种数据的id集合
        for (InteractionQuestion r : records) {
            userIds.add(r.getUserId());
            cIds.add(r.getCourseId());
            cataIds.add(r.getChapterId());
            cataIds.add(r.getSectionId());
        }
        // 3.2.根据id查询用户
        List<UserDTO> users = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (CollUtils.isNotEmpty(users)) {
            userMap=users.stream().collect(Collectors.toMap(UserDTO::getId,Function.identity()));
        }
        // 3.3.根据id查询课程
        List<CourseSimpleInfoDTO> cInfo = courseClient.getSimpleInfoList(cIds);
        Map<Long, CourseSimpleInfoDTO> courseMap = new HashMap<>(cIds.size());
        if (CollUtils.isNotEmpty(cInfo)) {
            courseMap=cInfo.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId,Function.identity()));
        }
        // 3.4.根据id查询章节
        List<CataSimpleInfoDTO> cataInfo = catalogueClient.batchQueryCatalogue(cataIds);
        Map<Long, String> cataMap = new HashMap<>(cataIds.size());
         cataMap = cataInfo.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        // 4.封装VO
        List<QuestionAdminVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion q : records) {
            // 4.1.将PO转VO，属性拷贝
            QuestionAdminVO vo = BeanUtils.copyBean(q, QuestionAdminVO.class);
            voList.add(vo);
            // 4.2.用户信息
            UserDTO user = userMap.get(q.getUserId());
            if (user != null) {
                vo.setUserName(user.getName());
            }
            // 4.3.课程信息以及分类信息
            CourseSimpleInfoDTO courseDTO = courseMap.get(q.getCourseId());
            if (courseDTO != null) {
                vo.setCourseName(courseDTO.getName());
            }
            // 4.4.章节信息
            vo.setChapterName(cataMap.getOrDefault(q.getChapterId(),""));
            vo.setSectionName(cataMap.getOrDefault(q.getSectionId(),""));
        }
        return PageDTO.of(page,voList);
    }

    @Override
    public QuestionAdminVO queryQuestionByIdAdmin(Long id) {
        //1.根据id查询数据
        InteractionQuestion question = getById(id);
        //2.数据校验
        if (question == null) {
            //没有数据或者被隐藏了
            return  null;
        }
        //2.PO转换为VO
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
        // 3.查询提问者信息
        UserDTO user = userClient.queryUserById(question.getUserId());
        if (user != null) {
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        //4.查询课程信息
        CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(question.getCourseId(),false,true);
        if (courseInfo != null) {
            // 4.1.课程名称信息
            vo.setCourseName(courseInfo.getName());
            // 4.2.分类信息
            vo.setCategoryName(categoryCache.getCategoryNames(courseInfo.getCategoryIds()));
            // 4.3.教师信息
            List<Long> teacherIds = courseInfo.getTeacherIds();
            List<UserDTO> teachers = userClient.queryUserByIds(teacherIds);
            if (CollUtils.isNotEmpty(teachers)) {
                String teacherName = teachers.stream()
                        .map(UserDTO::getName)
                        .collect(Collectors.joining("/"));
                vo.setTeacherName(teacherName);
            }
        }
        // 5.查询章节信息
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(
                List.of(question.getChapterId(), question.getSectionId())
        );
        Map<Long, String > cataMap = new HashMap<>(catas.size());
        if (CollUtils.isNotEmpty(catas)) {
            cataMap = catas.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        vo.setChapterName(cataMap.getOrDefault(question.getChapterId(),""));
        vo.setSectionName(cataMap.getOrDefault(question.getSectionId(),""));
        // 6.封装VO
        return vo;
    }

    @Override
    public void hiddenQuestion(Long id, Boolean hidden) {
        InteractionQuestion question = new InteractionQuestion();
        question.setId(id);
        question.setHidden(hidden);
        updateById(question);
    }
}
